TalentSync

AI resume builder and ATS optimizer for job seekers. Tailored resumes, outreach, and interview prep from one profile.

API client libraries

Frontend HTTP client, typed feature services, auth headers, and error handling against the FastAPI backend.

Repository layout#

The client layer spans the frontend services and Next.js API routes that proxy to the backend, along with authentication and error-handling utilities. The backend exposes REST endpoints under versioned prefixes.

Building blocks#

  • Generic HTTP client with typed requests and clear error handling
  • Typed service layer wrapping endpoints for specific features
  • Authentication via FastAPI cookies and getSession() / useSession()
  • Dynamic LLM provider headers resolved per user
  • Shared error extraction utility
  • API response typing for consistent frontend contracts
  • Toast-based loading and error notifications

Code to read:

  • Generic client and error types: api-client.ts
  • Service exports and usage: index.ts
  • Dashboard service example: dashboard.service.ts
  • Resume service example: resume.service.ts
  • LLM headers resolution: llm-headers.ts
  • Session helpers: lib/session.ts, session-provider.tsx
  • Error extraction utility: error-utils.ts
  • API response types: api.ts
  • Toast manager: use-toast.ts

How it fits together#

The frontend talks to BFF routes through api-client.ts. Services return typed payloads. Browser cookies stay on same-origin /api/v1. BFF-to-FastAPI calls add a minted Bearer plus X-LLM-* from llm-headers.ts.

Generic HTTP client#

The generic client wraps fetch :

  • Method helpers: get, post, put, patch, delete
  • Automatic JSON serialization for non-FormData bodies
  • Query string building from params
  • Reliable error handling via ApiError
  • Network error normalization

Typed service layer#

Services encapsulate endpoint logic and return typed responses. Examples:

  • Dashboard service: retrieves dashboard data
  • Resume service: CRUD and analysis operations for resumes

Authentication and session management#

Google OAuth on FastAPI. NextAuth is gone. Protected BFF routes call requireApiUser(). They mint a backend access JWT when proxying.

Dynamic LLM headers#

The LLM headers utility resolves provider, model, and optional API key for a given user and injects them into requests. This enables per-user routing to external LLM providers.

Error handling strategies#

The generic client normalizes network and server errors into ApiError instances. A shared utility extracts human-readable messages from thrown values. Components should catch ApiError and display messages.

Loading state management#

The toast manager is a small imperative helper to surface loading and error notifications. Components can trigger toasts while awaiting API responses and dismiss them upon completion.

Request/Response processing and endpoint consumption#

  • Query parameters are appended via URLSearchParams
  • Non-FormData bodies are serialized to JSON
  • Responses are parsed and returned; non-OK responses raise ApiError
  • Typed services wrap endpoints and return ApiResponse

References:

  • api-client.ts
  • api.ts

Backend integration approaches#

  • Frontend calls Next.js API routes that validate sessions and interact with Prisma
  • Backend FastAPI app defines CORS and request/response logging middleware
  • Routes are grouped under versioned prefixes (/api/v1, /api/v2)

References:

  • route.ts
  • main.py

Async/Await patterns and error propagation#

  • All service methods are async and await apiClient methods
  • ApiError carries HTTP status and raw payload for granular handling
  • Components should handle ApiError and use the toast manager for UX

References:

  • dashboard.service.ts
  • resume.service.ts
  • api-client.ts

Extending client functionality#

  • Add custom headers: pass additional headers in RequestOptions; the client merges them
  • Add new endpoints: define a new service method returning apiClient.get/post/etc.
  • Extend error handling: catch ApiError in components and branch on status/data

References:

  • api-client.ts
  • index.ts

Adding custom headers#

  • For LLM routing, use the LLM headers utility to inject provider/model/key
  • For other needs, pass headers in RequestOptions when calling apiClient methods

References:

  • llm-headers.ts
  • api-client.ts

Implementing custom error handling#

  • Use the shared error extraction utility to derive messages
  • In components, catch ApiError and decide whether to show a toast or redirect

References:

  • error-utils.ts

Client-Side caching strategies#

  • No explicit caching is implemented in the client. Consider integrating a caching layer (e.g., in-memory cache keyed by URL+params) to reduce redundant requests for identical queries.
  • For immutable resources, cache responses keyed by endpoint and parameters; invalidate on mutations.

[No sources needed since this section provides general guidance]

Retry mechanisms#

  • No built-in retry logic exists in the client. Implement retries with exponential backoff for transient failures (e.g., network errors, 5xx).
  • Respect AbortSignal to cancel ongoing requests during unmount or rapid successive calls.

[No sources needed since this section provides general guidance]

Timeout handling#

  • Use AbortSignal to enforce timeouts. Pass a signal with a timeout to apiClient methods and handle AbortError appropriately.

[No sources needed since this section provides general guidance]

Rate limiting#

  • No explicit rate limiting is enforced in the client. Implement client-side throttling or queueing for high-frequency operations.
  • Observe server-side rate limits and back off on 429 responses.

[No sources needed since this section provides general guidance]

Bulk operations#

  • Design batch endpoints on the backend and expose them via Next.js routes. On the frontend, split large lists into chunks and process sequentially or in controlled concurrency.

[No sources needed since this section provides general guidance]

Streaming response handling#

  • The current client parses entire JSON responses. For streaming responses, consider using a streaming parser or backend changes to support chunked responses.

[No sources needed since this section provides general guidance]

Dependencies#

Frontend services depend on api-client.ts. BFF routes depend on getSession() and Prisma for user-owned rows (payments, LLM config). FastAPI owns OAuth and /api/v1/auth.

Performance#

  • Minimize unnecessary re-fetches by caching responses and invalidating on mutation
  • Use AbortSignal to cancel stale requests
  • Batch frequent updates and debounce user-triggered actions
  • Prefer incremental loading for large datasets
  • Avoid blocking UI on long-running operations; use toasts and optimistic updates where appropriate

[No sources needed since this section provides general guidance]

Troubleshooting#

Common issues:

  • Unauthorized access: verify ts_access_token and requireApiUser()
  • Network errors: Inspect AbortError and avoid aborting signals early
  • Unexpected server errors: Log ApiError.status and ApiError.data for debugging
  • Message parsing: Use the shared error extraction utility to normalize messages

References:

  • api-client.ts
  • error-utils.ts

Appendix#

API endpoint consumption examples#

  • GET dashboard data: dashboard.service.ts
  • Upload resume (multipart/form-data): resume.service.ts
  • Delete resume with query param: resume.service.ts

Authentication flows#

  • Google OAuth and cookies: backend/app/routes/auth.py, frontend/lib/session.ts
  • Protected BFF route: requireApiUser() in lib/api-auth.ts

Data processing workflows#

  • Resume analysis pipeline (upload → analysis → update): resume.service.ts